package interfaces

import (
	"deploy/interfaces/db"
	"deploy/schema"
	"deploy/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"
)

// rpm包上传
func (s *Server)RpmSave(c *gin.Context) {
	result := schema.Result{}
	defer func() {
		if err := recover(); err != nil {
			if result.Code==0{
				result.Code = 400
			}
			result.Err = fmt.Sprintf("%s",err)
		}
		c.JSON(result.Code,result)
	}()
	req := schema.SchemaNewRpm{}
	//json.Validata(c)
	err := c.BindJSON(&req)
	if err != nil {
		log.Println(err.Error())
		panic("参数错误")
	}
	// 如果是服务器的 更新，否则新建。
	if req.Url[:len(s.Conf.FileServer.Rpm1)] == s.Conf.FileServer.Rpm1 ||
		req.Url[:len(s.Conf.FileServer.Rpm2)] == s.Conf.FileServer.Rpm2{
		// 查出上传包的信息
		obj := db.Rpm{}
		err = s.Db.GetRpmByRpmName(req.RpmName,&obj)
		if err!=nil{
			result.Code=404
			panic("没有查找到rpm: "+req.RpmName+err.Error())
			}
		update := map[string]interface{}{"server_name":req.ServerName,"version":req.Version,"user":req.User}
		log.Println("update:",update)
		log.Println(obj.ID)
		s.Db.UpdateRpmById(int(obj.ID),update)
		result.Msg="更新rpm信息成功"
	} else{
		rpm := db.Rpm{
		ServerName:req.ServerName,
		RpmName:req.RpmName,
		Url: req.Url,
		Version:req.Version,
		User:req.User,
		Md5 : req.Md5,
		Latest: false,
		}
		err = s.Db.NewRpm(&rpm)
		if err!=nil{
			log.Println("写入数据库出现异常:",err.Error())
			panic("写入数据库发生异常")
		}
		result.Msg="新建rpm包成功"
	}
	result.Code = http.StatusOK
}

// 文件上传
func (s *Server)FileUpload(c *gin.Context){
	result := schema.Result{}
	defer func() {
		if err := recover(); err != nil {
			if result.Code==0{
				result.Code = 400
			}
			result.Err = fmt.Sprintf("%s",err)
		}
		c.JSON(result.Code,result)
	}()
	// 注意此处的文件名和client处的应该是一样的
	file, header, err := c.Request.FormFile("file")
	if err != nil{
		panic("上传文件的参数错误")
	}
	filename := header.Filename
	user := c.Query("user")
	// 创建临时接收文件
	basePath := "./files/rpm/"
	baseFile := basePath + filepath.Base(filename)
	if utils.FileExist(baseFile){
		log.Println("上传rpm包：已存在相同文件 "+filename+"，覆盖!")
	}
	// 计算md5

	out, err := os.Create(baseFile)
	if err != nil {
		panic(err)
	}
	defer out.Close()
	// Copy数据
	_, err = io.Copy(out, file)
	if err != nil {
		panic(err)
	}
	// 计算md5值
	md5,err := utils.Md5sum(baseFile)
	if err != nil{
		panic("计算md5值时出现了错误:"+err.Error())
	}
	url := path.Join(s.Conf.FileServer.Rpm1,filename)+","+path.Join(s.Conf.FileServer.Rpm2+filename)
	// 写入数据库
	obj:=db.Rpm{}
	err =s.Db.GetRpmByRpmName(filename,&obj)
	if err!=nil{
		log.Println(err.Error())
		panic(err)
	}
	if obj.ID >0{
		err=s.Db.UpdateRpmById(int(obj.ID), map[string]interface{}{"rpm_name":filename,"url":url,"User":user,"md5":md5})
		if err!=nil{
			log.Println("写入数据库出现异常:",err.Error())
			panic("写入数据库发生异常")
		}
		log.Printf("上传文件%s 更新数据成功,md5: %s\n",baseFile,md5)
	} else {
		// 新建
		rpm := db.Rpm{
		RpmName:filename,
		Url: url,
		User: user,
		Md5 : md5,
		Latest: false,
	}
		err = s.Db.NewRpm(&rpm)
		if err!=nil{
			log.Println("写入数据库出现异常:",err.Error())
			panic("写入数据库发生异常")
		}
		log.Printf("上传文件%s写入数据库成功,md5: %s\n",baseFile,md5)}

	result.Msg="文件上传成功"
	result.Data=gin.H{"url":url,"md5":md5}
	result.Code=http.StatusOK
	//c.JSON(http.StatusOK,gin.H{"err":"","msg":"文件上传成功","data":gin.H{"url":url}})
}

// 直接从rpm仓库拉取rpm包，保存在服务器上
func (s *Server)GetRpmFileFromRepository(c *gin.Context){
	result := schema.Result{}
	defer func() {
		if err := recover(); err != nil {
			if result.Code==0{
				result.Code = 400
			}
			result.Err = fmt.Sprintf("%s",err)
		}
		c.JSON(result.Code,result)
	}()
	urlStr := c.Query("url")
	log.Println(urlStr)
	_, err := url.ParseRequestURI(urlStr) // 注意这里必须带有http/https协议， 否则会被认定非合法url
	if err != nil {
		fmt.Println(err)
		result.Code=400
		result.Err="url参数不合法"
		return
	}
	u, err := url.Parse(urlStr)
	if err != nil || u.Scheme == "" || u.Host == "" {
		log.Println("参数不合法,urlStr: ",urlStr)
		result.Code=400
		result.Err="url参数不合法"
		log.Println(err)
		return
	}
	res, err := http.Get(urlStr)
	if err != nil {
		log.Printf("Get%s Err: %v",urlStr,err)
		res, err = http.Get(urlStr)
		if err != nil{
			log.Printf("Get%s Err: %v",urlStr,err)
			result.Code=502
			result.Err="open url err "
			return
		}
	}
	contentType:=res.Header.Get("Content-Type")
	log.Println("contentType: ",contentType)
	// 如果 不是rpm包类型的文件
	if contentType == "application/x-rpm"{
		if res.StatusCode != 200{
			result.Code=res.StatusCode
			result.Err="拉取rpm失败"
			return
		}
		//读取服务器返回的文件大小
		fsize, err := strconv.ParseInt(res.Header.Get("Content-Length"), 10, 32)
		if err != nil {
			log.Printf("Get %s Err: %v",urlStr,err)
			result.Code=502
			result.Err="open url err"
			return
		}
		log.Println("下载文件大小为:",fsize)

		// 取出rpm包名
		keys := strings.Split(urlStr,"/")
		filename := keys[len(keys)-1]
		// 保存文件
		f, err := os.Create(fmt.Sprintf("./files/rpm/%s",filename))
		defer f.Close()
		if err != nil {
			log.Println("新建rpm包失败：",err.Error())
			result.Code=502
			result.Err="拉取rpm包失败"
			return
		}
		io.Copy(f, res.Body)

		// 计算md5值
		md5,err := utils.Md5sum(f.Name())
		if err != nil{
			panic("计算md5值时出现了错误:"+err.Error())
		}
		url := path.Join(s.Conf.FileServer.Rpm1,filename)+","+path.Join(s.Conf.FileServer.Rpm2+filename)
		// 写入数据库
		obj:=db.Rpm{}
		err =s.Db.GetRpmByRpmName(filename,&obj)
		if err!=nil{
			log.Println(err.Error())
			panic(err)
		}
		if obj.ID >0{
			err=s.Db.UpdateRpmById(int(obj.ID), map[string]interface{}{"rpm_name":filename,"url":url,"User":"root","md5":md5})
			if err!=nil{
				log.Println("写入数据库出现异常:",err.Error())
				panic("写入数据库发生异常")
			}
			log.Printf("拉取文件%s 更新数据成功,md5: %s\n",urlStr,md5)
		} else {
			// 新建
			rpm := db.Rpm{
				RpmName:filename,
				Url: url,
				User: "root",
				Md5 : md5,
				Latest: false,
			}
			err = s.Db.NewRpm(&rpm)
			if err!=nil{
				log.Println("写入数据库出现异常:",err.Error())
				panic("写入数据库发生异常")
			}
			log.Printf("拉取文件%s写入数据库成功,md5: %s\n",urlStr,md5)}

		result.Msg="拉取rpm包成功"
		result.Data=gin.H{"url":url,"md5":md5}
		result.Code=http.StatusOK
	}else{
		result.Code=404
		result.Err="请确认rpm包的地址"
		return
	}

}

func (s *Server)GetRpmDir(c *gin.Context){
	result := schema.Result{}
	data := []string{}
	defer func() {
		if err := recover(); err != nil {
			if result.Code==0{
				result.Code = 400
			}
			result.Err = fmt.Sprintf("%s",err)
		}
		result.Data=data
		c.JSON(result.Code,result)
	}()
	a:=utils.GetFileList("./files/rpm/")

	for _,f := range a{
		data = append(data, f.Name())
	}
}



